From: Phil Thompson Date: Mon, 13 Jul 2026 15:01:40 +0000 (+0100) Subject: Support for Python v3.15 X-Git-Tag: archive/raspbian/6.11.0-4+rpi1^2~1 X-Git-Url: https://dgit.raspbian.org/%22http://www.example.com/cgi/%22/%22http:/www.example.com/cgi/%22?a=commitdiff_plain;h=d44efd9d06a6e500b962078eb15a57bcfd38ea30;p=pyqt6.git Support for Python v3.15 The project can now be built with Python v3.15 (where the limited ABI version targeted will be v3.13). (cherry picked from commit 04c516de9e360ccea2407d5d3a72de3df161ceab) Gbp-Pq: Name Support-for-Python-v3.15.patch --- diff --git a/project.py b/project.py index 5af0317..5d9a527 100644 --- a/project.py +++ b/project.py @@ -105,6 +105,14 @@ del find_qt return dunder_init + def get_limited_abi_version(self): + """ Return the version number of the limited ABI to use. """ + + # We use PyWeakref_GetObject() which was removed from the limited API + # in Python v3.15. It's replacement, PyWeakref_GetRef() was added to + # the limited ABI in Python v3.13. + return (3, 13, 0) if sys.hexversion >= 0x030f0000 else None + def get_options(self): """ Return the sequence of configurable options. """ diff --git a/qpy/QtCore/qpycore_pyqtproperty.cpp b/qpy/QtCore/qpycore_pyqtproperty.cpp index da69665..3892231 100644 --- a/qpy/QtCore/qpycore_pyqtproperty.cpp +++ b/qpy/QtCore/qpycore_pyqtproperty.cpp @@ -511,7 +511,7 @@ static PyObject *pyqtProperty_reset(PyObject *self, PyObject *reset) static qpycore_pyqtProperty *clone(qpycore_pyqtProperty *orig) { qpycore_pyqtProperty *pp = (qpycore_pyqtProperty *)PyType_GenericNew( - Py_TYPE(orig), 0, 0); + Py_TYPE((PyObject *)orig), 0, 0); if (pp) { diff --git a/qpy/QtCore/qpycore_pyqtslot.cpp b/qpy/QtCore/qpycore_pyqtslot.cpp index 0dc4987..440a6d7 100644 --- a/qpy/QtCore/qpycore_pyqtslot.cpp +++ b/qpy/QtCore/qpycore_pyqtslot.cpp @@ -97,7 +97,9 @@ PyQtSlot::Result PyQtSlot::invoke(void **qargs, PyObject *self, void *result, else { // Use the value we have if one wasn't supplied. - if (!self) + if (self) + Py_INCREF(self); + else self = instance(); // If self is NULL then we didn't have a method in the first place. @@ -108,12 +110,18 @@ PyQtSlot::Result PyQtSlot::invoke(void **qargs, PyObject *self, void *result, // See if the instance has gone (which isn't an error). if (self == Py_None) + { + Py_DECREF(self); return PyQtSlot::Ignored; + } // If the receiver wraps a C++ object then ignore the call if it no // longer exists. if (!no_receiver_check && PyObject_TypeCheck(self, sipSimpleWrapper_Type) && !sipGetAddress((sipSimpleWrapper *)self)) + { + Py_DECREF(self); return PyQtSlot::Ignored; + } sipMethodDef callable_m; @@ -121,6 +129,7 @@ PyQtSlot::Result PyQtSlot::invoke(void **qargs, PyObject *self, void *result, callable_m.pm_self = self; callable = sipFromMethod(&callable_m); + Py_DECREF(self); } // Convert the C++ arguments to Python objects. @@ -181,7 +190,11 @@ bool PyQtSlot::operator==(PyObject *callable) const if (other) return false; - return (mfunc == callable_m.pm_function && instance() == callable_m.pm_self); + PyObject *instance_obj = instance(); + bool res = (mfunc == callable_m.pm_function && instance_obj == callable_m.pm_self); + Py_XDECREF(instance_obj); + + return res; } if (!other) @@ -202,14 +215,30 @@ bool PyQtSlot::operator==(PyObject *callable) const } -// Get the instance object. +// Get a strong reference to the instance object, otherwise return NULL or a +// strong referenc to Py_None. PyObject *PyQtSlot::instance() const { + PyObject *instance_obj; + // Use the weak reference if possible. if (mself_wr) - return PyWeakref_GetObject(mself_wr); + { +#if PY_VERSION_HEX >= 0x030f0000 + if (PyWeakref_GetRef(mself_wr, &instance_obj) < 0) + instance_obj = NULL; +#else + instance_obj = PyWeakref_GetObject(mself_wr); + Py_XINCREF(instance_obj); +#endif + } + else + { + instance_obj = mself; + Py_XINCREF(instance_obj); + } - return mself; + return instance_obj; } diff --git a/qpy/QtCore/qpycore_qobject_helpers.cpp b/qpy/QtCore/qpycore_qobject_helpers.cpp index f839b30..a84cf57 100644 --- a/qpy/QtCore/qpycore_qobject_helpers.cpp +++ b/qpy/QtCore/qpycore_qobject_helpers.cpp @@ -50,7 +50,7 @@ static int qt_metacall_worker(sipSimpleWrapper *pySelf, PyTypeObject *pytype, const QMetaObject *qpycore_qobject_metaobject(sipSimpleWrapper *pySelf, sipTypeDef *base) { - sipWrapperType *wt = (pySelf ? (sipWrapperType *)Py_TYPE(pySelf) : 0); + sipWrapperType *wt = (pySelf ? (sipWrapperType *)Py_TYPE((PyObject *)pySelf) : 0); return qpycore_get_qmetaobject(wt, base); } @@ -64,7 +64,8 @@ int qpycore_qobject_qt_metacall(sipSimpleWrapper *pySelf, sipTypeDef *base, if (!pySelf) return -1; - return qt_metacall_worker(pySelf, Py_TYPE(pySelf), base, _c, _id, _a); + return qt_metacall_worker(pySelf, Py_TYPE((PyObject *)pySelf), base, _c, + _id, _a); } @@ -220,10 +221,10 @@ bool qpycore_qobject_qt_metacast(sipSimpleWrapper *pySelf, // We only need to look at the MRO if the object is a wrapped type (rather // than a user sub-class). - if (base_pytype != Py_TYPE(pySelf)) + if (base_pytype != Py_TYPE((PyObject *)pySelf)) { - PyObject *mro = PyObject_GetAttr((PyObject *)Py_TYPE(pySelf), - qpycore_dunder_mro); + PyObject *mro = PyObject_GetAttr( + (PyObject *)Py_TYPE((PyObject *)pySelf), qpycore_dunder_mro); Q_ASSERT(mro); for (Py_ssize_t i = 0; i < PyTuple_Size(mro); ++i)